import datetime
import os.path
import typing as tp

import pygit2


class RemoteInfo(tp.TypedDict):
    name: str
    url: str

class BranchInfo(tp.TypedDict):
    name: str
    oid: str
    remote: str


class AuthorInfo(tp.TypedDict):
    name: str
    email: str


class CommitInfo(tp.TypedDict):
    name: str   # shortID
    message: str
    oid: str
    is_merged: bool

    commit_time: datetime.datetime
    parents: tp.List[str]   # commit oid
    author_email: str # author name
    committer_email: str # author name
    owner_branch: str  # branch name


class GitRepoScanner:
    def __init__(self, path: str):
        self._path = path
        try:
            self._repo = pygit2.Repository(path)
        except pygit2.errors.GitError:
            raise ValueError(f"导入git仓库失败: {path}")

        self.repo_name = os.path.basename(self._path)

    def get_all_branch(self) -> tp.List[BranchInfo]:
        result = []
        for item in self._repo.branches.remote:
            ref = self._repo.references[f"refs/remotes/{item}"]
            oid = str(ref.target)
            if oid.startswith("refs/remotes"):
                continue
            remote = ref.shorthand.split("/")[0]
            result.append(BranchInfo(
                name=item[len(remote)+1:],
                oid=oid,
                remote=remote,
            ))
        return result

    def get_all_branch_commit(self):
        for branch in self.get_all_branch():
            self.get_branch_commit(branch["name"])

    def get_branch_commit(self, branch_name: str) -> tp.List[CommitInfo]:
        result = []
        branch = self._repo.lookup_branch(branch_name, pygit2.GIT_BRANCH_REMOTE)
        for commit in self._repo.walk(branch.target, pygit2.GIT_SORT_TIME):
            result.append(CommitInfo(
                name=commit.short_id,
                message=commit.message,
                oid=str(commit.id),
                is_merged=commit.message.startswith("Merge branch "),

                commit_time=datetime.datetime.fromtimestamp(commit.commit_time),
                parents=[str(item.id) for item in commit.parents],
                author_email=commit.author.email,
                committer_email=commit.committer.email,
                owner_branch=branch_name
            ))
            print(f"<{branch_name}> - {commit.author.email}")
        return result


if __name__ == "__main__":
    s = GitRepoScanner(r"D:\c\redis")
    s.get_all_branch_commit()